<!doctype html>
<html>
<head>
  <title>Vis Network | Data | Dynamic filtering</title>

  <script type="text/javascript" src="../../../standalone/umd/vis-network.min.js"></script>

  <style type="text/css">
    #mynetwork {
      width: 600px;
      height: 400px;
      border: 1px solid lightgray;
    }
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
        "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
        sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }
    code {
      font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
    }
  </style>
</head>
<body>
  <h1>Dynamic filtering</h1>
  <p>
    With <a
      href="https://visjs.github.io/vis-data/data/dataview.html"
      target="_blank">
    <code>vis.DataView</code></a>
    on top of vis.DataSet you can filter displayed data without modifying the data source.
  </p>
  <label>
    Filter nodes
    <select id='nodeFilterSelect'>
      <option value=''>All characters</option>
      <option value='kid'>kids</option>
      <option value='adult'>adults</option>
      <option value='male'>male</option>
      <option value='female'>female</option>
    </select>
  </label>
  <br>
  <br>
  <label>
    Filter edges
    <div>
      <label>
        <input type='checkbox' name='edgesFilter' value='parent' checked></input>
        Is <span style="color:green">parent</span> of
      </label>
    </div>
    <div>
      <label>
        <input type='checkbox' name='edgesFilter' value='teacher' checked></input>
        Is <span style="color:blue">teacher</span> of
      </label>
    </div>
    <div>
      <label>
        <input type='checkbox' name='edgesFilter' value='friend' checked></input>
        Is <span style="color:red">friend</span> of
      </label>
    </div>
  </label>
  <br></br>
  <div id="mynetwork"></div>
  <script type="text/javascript">

    const nodeFilterSelector = document.getElementById('nodeFilterSelect')
    const edgeFilters = document.getElementsByName('edgesFilter')


    function startNetwork(data) {
      const container = document.getElementById('mynetwork')
      const options = {}
      new vis.Network(container, data, options)
    }

    /**
     * In this example we do not mutate nodes or edges source data.
     */
    const nodes = new vis.DataSet([
      { id: 1, label: 'Eric Cartman', age: 'kid', gender: 'male' },
      { id: 2, label: 'Stan Marsh', age: 'kid', gender: 'male' },
      { id: 3, label: 'Wendy Testaburger', age: 'kid', gender: 'female' },
      { id: 4, label: 'Mr Mackey', age: 'adult', gender: 'male' },
      { id: 5, label: 'Sharon Marsh', age: 'adult', gender: 'female' }
    ])

    const edges = new vis.DataSet([
      { from: 1, to: 2, relation: 'friend', arrows: 'to, from', color: { color: 'red'} },
      { from: 1, to: 3, relation: 'friend', arrows: 'to, from', color: { color: 'red'} },
      { from: 2, to: 3, relation: 'friend', arrows: 'to, from', color: { color: 'red'} },
      { from: 5, to: 2, relation: 'parent', arrows: 'to', color: { color: 'green'} },
      { from: 4, to: 1, relation: 'teacher', arrows: 'to', color: { color: 'blue'} },
      { from: 4, to: 2, relation: 'teacher', arrows: 'to', color: { color: 'blue'} },
      { from: 4, to: 3, relation: 'teacher', arrows: 'to', color: { color: 'blue'} },
    ])

    /**
     * filter values are updated in the outer scope.
     * in order to apply filters to new values, DataView.refresh() should be called
     */
    let nodeFilterValue = ''
    const edgesFilterValues = {
      friend: true,
      teacher: true,
      parent: true
    }

    /*
      filter function should return true or false
      based on whether item in DataView satisfies a given condition.
    */
    const nodesFilter = (node) => {
      if (nodeFilterValue === '') {
        return true
      }
      switch(nodeFilterValue) {
        case('kid'):
          return node.age === 'kid'
        case('adult'):
          return node.age === 'adult'
        case('male'):
          return node.gender === 'male'
        case('female'):
          return node.gender === 'female'
        default:
          return true
      }
    }

    const edgesFilter = (edge) => {
      return edgesFilterValues[edge.relation]
    }

    const nodesView = new vis.DataView(nodes, { filter: nodesFilter })
    const edgesView = new vis.DataView(edges, { filter: edgesFilter })


    nodeFilterSelector.addEventListener('change', (e) => {
      // set new value to filter variable
      nodeFilterValue = e.target.value
      /*
        refresh DataView,
        so that its filter function is re-calculated with the new variable
      */
      nodesView.refresh()
    })

    edgeFilters.forEach(filter => filter.addEventListener('change', (e) => {
      const { value, checked } = e.target
      edgesFilterValues[value] = checked
      edgesView.refresh()
    }))

    startNetwork({ nodes: nodesView, edges: edgesView })

  </script>
</body>
</html>
